About Providers
A provider is a layered set of protocols, implemented by Streams modules, that provides some kind of data-oriented service. That service might be implementing a networking protocol, encrypting data, filtering data, and so on. When you configure a provider, you can layer the modules that implement the provider to create an arbitrarily complex service for client applications. For example, you can place an encryption module above the AppleTalk Data Stream Protocol (ADSP) module, which is placed above an EtherTalk module. This combination would provide a networking stream of data that was secure from snooping on the network.Open Transport defines three main kinds of providers:
An endpoint provider offers a service that creates connections and moves data from one logical address to another. A mapper provider offers services that you use to associate, or "map," network entity names with network addresses. A service provider lets you perform tasks that are specific to a particular protocol, such as AppleTalk or TCP/IP. There is one type of service provider for each protocol family that Open Transport supports.
- endpoint providers
- mapper providers
- service providers
In the normal course of events you do not communicate directly with the Streams modules that make up a provider. For example, to use the services of an endpoint provider, you must open an endpoint and use the functions defined in the Open Transport application programming interface (API) for endpoints. The Open Transport API shields your application from the details of the provider implementation, allowing your application to run with little or no change, even when the implementation of the provider is changed, updated, or moved from one platform to another.
To use the services offered by a provider, you must initialize Open Transport and then call the function that opens the provider. When that function returns, it passes back to you a reference to the provider you have just created. A provider reference is like a file handle or a driver reference number. It associates a function called from your application with a specific provider that must implement the function; you pass the provider reference as a parameter to all provider functions. The data type of a provider reference depends on the type of the provider (endpoint reference, mapper reference, AppleTalk service reference, and so on).
You can open one provider or many. For example, a server application might open many providers and use them concurrently. The number of providers you can create is limited mainly by the availability of system resources, such as memory. The memory used to create a provider comes partly from your application heap (approximately 8 bytes) but mostly from the system heap. If you allocate data structures while using a provider, the memory for the data structures is allocated entirely from your application heap.
- C++ Note
- Providers are objects, and each main type of provider is a class. Specifically, endpoints, mappers, and the service providers are all subclasses of the
TProvider
class. Each type of object has a defined C++ interface.![]()
Provider Functions
Functions that manipulate providers are known as provider functions. Some provider functions can manipulate providers of any type. These are called general provider functions and they are documented in the reference section of this chapter. You use general provider functions to
In addition to the general provider functions, each type of provider has type-specific provider functions; these functions work with only that particular type of provider. For example, endpoint functions work only with endpoint providers, and mapper functions work only with mapper providers. Each kind of service provider (for AppleTalk, TCP/IP, and so on) has its own type-specific provider functions. There are no type-specific provider functions that work with more than one type of service provider.
- get or set a provider's default mode of operation, which determines whether provider functions execute synchronously or asynchronously, whether a provider can wait to send or receive data, and whether functions that send data acknowledge having sent the data.
- install and remove a notifier callback function, which the provider uses to pass information to your application
- send a module-specific command, which allows you to communicate directly with the Streams modules that make up your provider
- close a provider
Provider functions that accept a provider reference of type
ProviderRef
are general: they accept any other type of provider reference as well. But functions that require a type of provider reference other thanProviderRef
(for example,EndpointRef
) are type-specific: they accept only that type of provider reference.
You cannot call most provider functions or other Open Transport functions at interrupt time. You cannot include these functions in any interrupt routine from an external device, VBL task, Time Manager task, or Deferred Task Manager task. You can only call these functions at system task time (primary interrupt level) or at deferred task time (secondary interrupt level) scheduled by the Open Transport function
- C++ Note
- You can call public member functions of the
TProvider
class from any provider: these functions are the general provider functions. Public member functions defined in a subclass of theTProvider
class (for example,TEndpoint
) can be called only from providers belonging to that subclass (in this example, only from theTEndpoint
subclass): these are the type-specific provider functions. Note that, like endpoints and mappers, each kind of service provider (for AppleTalk, TCP/IP, and so on) derives directly from theTProvider
class; there is no common class of service providers.![]()
OTScheduleDeferredTask
. For more information and a list of those functions you can call from an interrupt, see the chapter "Process Management" in this book.Modes of Operation
For each provider, you can use general provider functions to specify
For more information about how you use general provider functions to control a provider's mode of operation, see the section "Controlling a Provider's Modes of Operation" on page 2-8.
- how provider functions execute
In synchronous mode, provider functions return only when they complete execution. In asynchronous mode, they return as soon as they are queued for execution. Applications running under an operating system that does not use threads, can avoid awkward delays and generally improve performance by calling functions asynchronously.
- the provider's blocking status
A provider's blocking status affects how functions that send and receive data behave when they must wait to complete an operation. If a provider is blocking, it waits for as long as it takes to send or receive data. If a provider is nonblocking, the provider attempts to send or receive data and, if it cannot do so immediately, it returns with a result indicating why it could not complete the operation.
- the provider's send-acknowledgment status
A provider's send-acknowledgment status determines whether endpoint functions that send data make an internal copy of the data before sending it and whether they advise the provider when the data has actually been sent. Open Transport ignores the send-acknowledgment status for mapper, AppleTalk Services, and TCP/IP providers.
Provider Events
Open Transport defines two kinds of events called provider events. These events are unique to the Open Transport architecture and not events in the usual Macintosh sense: they are not processed by the Event Manager, and they have no associated event record. Rather, Open Transport uses provider events to inform your application that something has occurred which demands your immediate attention or to signal the fact that a function executing in asynchronous mode has completed. The first kind of event is called an asynchronous event; the second kind of event is called a completion event. In this book, the term event refers to a provider event, except where noted otherwise.A provider uses asynchronous events to notify your application that data has arrived or that a request for a connection or disconnection is pending. Most asynchronous events defined for Open Transport have equivalents in the X/Open Transport Interface (XTI), from which the Open Transport interface derives. XTI does not define completion events. As just mentioned, a provider uses completion events to notify your application that an asynchronous function has finished executing. Some functions are inherently synchronous and have no corresponding completion event. For example, if an endpoint provider is in asynchronous mode and you execute the
OTGetEndpointState
function, the function returns information about the state of the endpoint immediately. The description of a function indicates whether the function behaves differently in asynchronous mode.A provider event is identified by a provider event code. These are listed and described in the event codes enumeration beginning on page 2-17. All provider event codes begin with the prefix
T_
, as inT_DATA
. Provider event codes for completion events end in the suffixCOMPLETE,
as inT_BINDCOMPLETE
. Codes for asynchronous events have no uniform suffix.In general, to receive notice of provider events, you must provide a notifier function and install it for the provider. A notifier function is a function that you write and that the provider can call when an event occurs. When the provider calls this function, it uses the function's parameters to pass back information about the event that occurred, and if this is a completion event, it also passes back additional information about the result of the function that completed and a pointer to any other information passed back by the function. The section "Using Notifier Functions to Handle Provider Events," beginning on page 2-12 provides additional information about notifier functions and the issues involved in asynchronous processing. You can also refer to "Application-Defined Functions," beginning on page 2-44 for a description of the notifier function.